package com.fattyCorps.game.service.rank;

import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

@Data
public class Rank {
    private volatile LinkedList<RankElem> list = new LinkedList<>();

    @JSONField(serialize = false)
    private volatile List<RankElem> readList = null;
    private int maxSize = 50;
    private volatile int min;

    public void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }

    // 提供一个外部可获取排行榜数据的接口
    @JSONField(serialize = false)
    public List<RankElem> getElems() {
//        synchronized (list) {
//            return new ArrayList<>(list);
//        }

        if (readList == null) {
            synchronized (list) {
                if (readList == null) {
                    readList = new ArrayList<>(list);
                }
            }
        }

        return readList;
    }

    public void init(List<RankElem> initList) {
        list = new LinkedList<>(initList);
    }

    // 插入排行榜数据
    public void insert(RankElem elem) {
        if (list.size() >= maxSize && elem.getScore() <= min)
        {
            return;
        }

        synchronized (list) {
            // 插入位置
            int inPos = -1;
            // 自己老数据位置
            int selfPos = -1;
            // 找出新元素在排行榜中可插入的位置，以及自己老数据的位置

            for (int i = 0; i < list.size(); i++) {
                if (inPos == -1) {
                    if (list.get(i).getScore() < elem.getScore()) {
                        inPos = i;
                    }
                }

                if (selfPos == -1) {
                    if (list.get(i).getPlayerId().equals(elem.getPlayerId())) {
                        selfPos = i;
                    }
                }

                // 两个都找到可以不用再搜索了
                if (inPos > -1 && selfPos > -1) {
                    break;
                }
            }

            // 如果原来在排行榜中
            if (selfPos > -1) {
                // 如果新数据也能上榜，并且大于原来的排行，就删除原来的，插入新的
                if (inPos > -1 && inPos < selfPos) {
                    // 一定要先删再添加，不然添加后selfPos值就错位了
                    list.remove(selfPos);
                    list.add(inPos, elem);
                    afterInsert();
                }
                // 如果新老位置相同，说明新数据值要大于老数据，就更新
                else if (inPos == selfPos) {
                    list.set(inPos, elem);
                    afterInsert();
                }
            }
            // 如果原来不在榜中
            else{
                // 新数据可上榜,插入新数据，根据排行榜是否满来决定是否删除最后一个数据
                if (inPos > -1) {
                    list.add(inPos, elem);
                    if (list.size() > maxSize) {
                        list.removeLast();
                    }

                    afterInsert();
                } else {
                    // 新数据没有上榜，但是榜单还没有满，插入到排行榜末尾
                    if (list.size() < maxSize) {
                        list.addLast(elem);
                        afterInsert();
                    }
                }

            }
        }
    }

    private void afterInsert() {
        readList = null;
        min = list.getLast().getScore();
    }
}
